/*
 * 2022/1/10	9:32	yin
 */

#if 0

	栈是最基础的数据结构之一。

	从技术上说，栈就是CPU寄存器里的某个指针所指向的一片内存区域。这里所说的"某个指针"通常位于x86/x64平台的ESP/RSP，ARM的SP。

	操作栈的最常见的指令是push/pop。
	push 会对ESP/RSP/SP的值进行减法运算，使之减去 4(32 bit)或 8(64 bit)，然后将操作数写到上述寄存器里的指针所指向的内存中。

	pop 先从栈指针(stack pointer)指向的内存中读取数据，用以备用(通常是写到其他寄存器里),然后再将栈指针的数值加上 4 或 8 。 

	在分配栈的空间之后，栈指针，即stack pointer所指向的地址是栈的底部。push 将减少栈指针的数值，而 pop 会增加它的数值。
	栈的"底"实际上使用的是整个栈的最低地址，即是整个栈的启动内存地址。

/*
 * 栈的用途
 */
	1.保存函数结束时的返回地址

	/* x86 */
	当程序使用call调用其他函数时，call指令结束后的返回地址将被保存在栈里；
	在call所调用的函数结束之后，程序将执行无条件跳转指令，跳转到这个返回地址。

	call 等价于 "PUSH 返回地址" 和 "JMP 函数地址" 的指令对。

	被调用函数里的RET指令，会从栈中读取返回地址，然后跳转到这个地址，就相当于"POP 返回地址" + "JMP 返回地址"指令。

	栈是有限的，溢出它很容易。直接使用无限递归，本就会满。

	/* arm */
	ARM程序也使用栈保存返回地址，只是略有不同。程序的返回地址保存在LR里。但是，如果程序还会继续调用其他函数，就需要在调用函数
	之前保存LR的值。通常，函数会在启动过程中(序言处)保存LR的值。通常在函数序言处看到"push R4-R7，LR", 并在尾声处看到
	"pop R4-R7, PC"。这些指令会对函数自身将要用到的寄存器进行保护，把它们的值放在栈中---也包括LR。

	如果一个函数不调用其他函数，它就像对上的枝杈末端的叶子那样。这种函数就叫作"叶函数(leaf function)"。叶函数的特点是，它不必
	保存LR的值。如果叶函数的代码短到用不到几个寄存器，那么它可能根本不会使用数据栈。所以，调用叶函数的时候确实可能不会涉及栈
	操作。这种情况下，因为这种代码不在外部内存RAM进行与栈有关的操作，所以它的运行速度有可能超过X86系统。在没有分配栈或者不可能
	用栈的时候，这类函数就会显现出优势。

	2.参数传递 
	
		esp	+ 4		:	返回地址
		esp + 8		:	参数一
		ese + c		:	参数二
		ese + 10	:	参数三

	3.存储局部变量

	4.alloca
	
	alloca函数直接使用栈来分配内存，除此之外，它与malloc没有显著区别。用完退出，自动释放。

/*
 * 栈的噪音
 */	
	原有栈空间里的局部变量不会被 自动清除，就成为了噪音或脏数据了。


#endif

void main()
{}